﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace PocketPasswordGen
{
    public class Clipboard
    {
        #region Win32 API ------------------------------------------------------------

        private const uint CF_UNICODETEXT = 13;

        [DllImport("Coredll.dll")]
        private static extern bool OpenClipboard(IntPtr hWndNewOwner);

        [DllImport("Coredll.dll")]
        private static extern bool CloseClipboard();

        [DllImport("Coredll.dll")]
        private static extern bool EmptyClipboard();

        [DllImport("Coredll.dll")]
        private static extern bool IsClipboardFormatAvailable(uint uFormat);

        [DllImport("Coredll.dll")]
        private static extern IntPtr GetClipboardData(uint uFormat);

        [DllImport("Coredll.dll")]
        private static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);

        [DllImport("Coredll.dll")]
        private static extern IntPtr LocalAlloc(int uFlags, int uBytes);

        #endregion -------------------------------------------------------------------

        #region Internal support functions

        private static IntPtr hMem = IntPtr.Zero;
        
        /// <summary>
        /// Copy data from string to a pointer
        /// </summary>
        /// <param name="dest"></param>
        /// <param name="src"></param>
        private unsafe static void CopyToPointer(IntPtr dest, string src)
        {
            int x;
            char* pDest = (char*)dest.ToPointer();

            for (x = 0; x < src.Length; x++)
            {
                pDest[x] = src[x];
            }
            pDest[x] = '\0';  // Add the null terminator.
        }

        /// <summary>
        /// Convert a pointer to string
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        private unsafe static string ConvertToString(IntPtr src)
        {
            int x;
            char* pSrc = (char*)src.ToPointer();
            StringBuilder sb = new StringBuilder();

            for (x = 0; pSrc[x] != '\0'; x++)
            {
                sb.Append(pSrc[x]);
            }
            return sb.ToString();
        }

        #endregion

        #region Public methods

        /// <summary>
        /// Check if data is available on the clipboard
        /// </summary>
        public static bool IsDataAvailable
        {
            get
            {
                return IsClipboardFormatAvailable(CF_UNICODETEXT);
            }
        }

        /// <summary>
        /// Set data on the clipboard
        /// </summary>
        /// <param name="strText"></param>
        /// <returns></returns>
        public unsafe static bool SetData(string strText)
        {
            if (OpenClipboard(IntPtr.Zero) == false)
            {
                return false;
            }

            hMem = LocalAlloc(0, ((strText.Length + 1) * sizeof(char)));

            if (hMem.ToInt32() == 0)
            {
                return false;
            }

            CopyToPointer(hMem, strText);

            EmptyClipboard();

            SetClipboardData(CF_UNICODETEXT, hMem);

            CloseClipboard();

            return true;
        }

        /// <summary>
        /// Get data from the clipboard
        /// </summary>
        /// <returns></returns>
        public static string GetData()
        {
            IntPtr hData;

            string strText;

            if (IsDataAvailable == false)
            {
                return null;
            }

            if (OpenClipboard(IntPtr.Zero) == false)
            {
                return null;
            }

            hData = GetClipboardData(CF_UNICODETEXT);

            if (hData.ToInt32() == 0)
            {
                return null;
            }

            strText = ConvertToString(hData);

            CloseClipboard();

            return strText;
        }

        public static void Cut(TextBox txtBox)
        {
            // Copy the data to the clipboard
            SetData(txtBox.SelectedText);

            // Remove selected text
            txtBox.SelectedText = "";
        }

        public static void Copy(TextBox txtBox)
        {
            // Copy the data to the clipboard
            SetData(txtBox.SelectedText);
        }

        public static void Paste(TextBox txtBox)
        {
            if (IsDataAvailable)
            {
                txtBox.SelectedText = GetData();
            }
        }

        #endregion
    }
}
